package cn.sccl.common.scheduler;

import cn.sccl.common.scheduler.enums.JobStateEnum;
import cn.sccl.common.scheduler.model.TaskFireLog;
import cn.sccl.common.util.HttpUtils;
import com.alibaba.fastjson.JSON;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;

import java.sql.Timestamp;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 调度监听器
 *
 * @author _minus
 * @create 2017-10-04 14:18
 */
public class JobListener implements org.quartz.JobListener {
	private static Log logger = LogFactory.getLog(JobListener.class);

	@Autowired
	private SchedulerService schedulerService;
	// 线程池
	private static ExecutorService executorService = Executors.newCachedThreadPool();

	public static String JOB_LOG = "jobLog";

	@Override
	public String getName() {
		return "taskListener";
	}

	@Override
	public void jobExecutionVetoed(JobExecutionContext context) {
	}

	/**
	 * 任务开始前
	 * @param context
     */
	@Override
	public void jobToBeExecuted(final JobExecutionContext context) {
		final JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
		String targetObject = jobDataMap.getString("targetObject");
		String targetMethod = jobDataMap.getString("targetMethod");
		if (logger.isInfoEnabled()) {
			logger.info("定时任务准备执行：{"+ targetObject+"}{"+ targetMethod+"}");
		}
		// 每一次任务执行记录下日志
		TaskFireLog log = initTaskFireLogByJobExecutionContext(context,jobDataMap);
		//保存日志
		schedulerService.updateLog(log);
		jobDataMap.put(JOB_LOG, log);
	}

	private TaskFireLog initTaskFireLogByJobExecutionContext(JobExecutionContext context,JobDataMap jobDataMap) {
		TaskFireLog log = new TaskFireLog();

		String targetObject = jobDataMap.getString("targetObject");
		String targetMethod = jobDataMap.getString("targetMethod");
		String group  =jobDataMap.getString("group");
		String taskName  =jobDataMap.getString("taskName");
		String targetParams = jobDataMap.getString("targetParams");

		log.setStartTime(new Timestamp(context.getFireTime().getTime()));
		log.setGroupName(group);
		log.setTaskName(taskName);
		log.setTargetMethod(targetMethod);
		log.setTargetObject(targetObject);
		log.setTargetParams(targetParams);

		log.setStatus(JobStateEnum.INIT_STATS.getCode().toString());
		log.setServerHost(HttpUtils.getHostName());

		return log  ;

	}

	// 任务结束后
	@Override
	public void jobWasExecuted(final JobExecutionContext context, JobExecutionException exp) {
		Timestamp end = new Timestamp(System.currentTimeMillis());
		final JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
		String targetObject = jobDataMap.getString("targetObject");
		String targetMethod = jobDataMap.getString("targetMethod");
		if (logger.isInfoEnabled()) {
			logger.info("定时任务执行完毕：{"+ targetObject+"}{"+ targetMethod+"}");

		}
		// 更新任务执行状态
		final TaskFireLog log = (TaskFireLog) jobDataMap.get(JOB_LOG);
		if (log != null) {
			log.setEndTime(end);
			if (exp != null) {
				logger.error("定时任务失败: [" + targetObject + "." + targetMethod + "]", exp);
				log.setStatus(JobStateEnum.TASK_ERROR.getCode().toString());
				log.setFireInfo(exp.getMessage());
			} else {
				//避免在准备状态下，不报错，没有执行的状态
				if (log.getStatus().equals(JobStateEnum.TASK_RUNNING.getCode().toString())) {
					log.setStatus(JobStateEnum.TASK_SUCCESS.getCode().toString());
				}
			}
		}
		executorService.submit(new Runnable() {
			@Override
			public void run() {
				if (log != null) {
					try {
						schedulerService.updateLog(log);
					} catch (Exception e) {
						logger.error("Update TaskRunLog cause error. The log object is : " + JSON.toJSONString(log), e);
					}
				}
			}
		});
	}

}
